﻿#ifndef SANEDEVICEOPTION_H
#define SANEDEVICEOPTION_H

#include "sane.h"
#include "saneopts.h"

#include <QObject>
#include <QWidget>
#include <QHBoxLayout>
#include <QSpinBox>
#include <QComboBox>
#include <QCheckBox>
#include <QToolBox>
#include <QLabel>
#include <QLineEdit>


class SaneOption : public /*QHBoxLayout*/ QWidget
{
	Q_OBJECT

private:
	SANE_Handle m_handle;
	int m_index;
	const SANE_Option_Descriptor* m_descriptor;
	QString m_name;
	SANE_Bool m_bool;
	SANE_Int m_int;
	SANE_Fixed m_fixed;
	SANE_Char m_string [200];

	QHBoxLayout* m_layout;
	QSpinBox* m_spin;
	QDoubleSpinBox* m_doubleSpin;
	QComboBox* m_combo;
	QCheckBox* m_check;
	QLineEdit* m_lineEdit;


	QString title () { return QString (m_descriptor->title); }
	QString description () { return QString (m_descriptor->desc ? m_descriptor->desc : ""); }
	QString unit ();

	// types et widgets
	SANE_Value_Type valueType () { return m_descriptor->type; }
	SANE_Constraint_Type constraintType () { return m_descriptor->constraint_type; }

	bool hasConstraintRange () { return constraintType () == SANE_CONSTRAINT_RANGE; }
	bool hasConstraintWordList () { return constraintType () == SANE_CONSTRAINT_WORD_LIST; }
	bool hasConstraintStringList () { return constraintType () == SANE_CONSTRAINT_STRING_LIST; }
	bool hasConstraintNone () { return constraintType () == SANE_CONSTRAINT_NONE; }

	bool valueIsBool () { return valueType () ==  SANE_TYPE_BOOL; }
	bool valueIsInt () { return valueType () == SANE_TYPE_INT; }
	bool valueIsDouble () { return valueType () == SANE_TYPE_FIXED; }
	bool valueIsString () { return valueType () ==  SANE_TYPE_STRING; }
	bool valueIsNumeric () { return ! valueIsString (); }

	bool widgetIsCheckBox () { return valueIsBool (); }
	bool widgetIsSpin () { return hasConstraintRange () && valueIsInt (); }
	bool widgetIsDoubleSpin () { return hasConstraintRange () && valueIsDouble (); }
	bool widgetIsCombo () { return hasConstraintWordList () || hasConstraintStringList (); }
	bool widgetIsLineEdit () { return hasConstraintNone () && !valueIsBool (); }

	QVariant widgetValue ();
	enum { CheckBox, Spin, DoubleSpin, Combo, LineEdit };

	int widgetType ()
	{
		if (widgetIsCheckBox ())
			return CheckBox;
		if (widgetIsCombo ())
			return Combo;
		if (widgetIsSpin ())
			return Spin;
		if (widgetIsDoubleSpin ())
			return DoubleSpin;
		if (widgetIsLineEdit ())
			return LineEdit;
		return -1;
	}

	QList<QVariant> possibleValues ();
	QVariant guiValue();
	QVariant deviceValue ();

public slots:
	SANE_Status guiToDevice ();

public:
	SaneOption (QWidget* parent, SANE_Handle handle, int index, const SANE_Option_Descriptor* descr);
	~SaneOption ();
	void initWidget();
	const QString& name () { return m_name; }
	void setGuiValue (const QString &str);
	SANE_Status deviceToGui ();
	const QString guiStrValue ();
	bool isActive () {
		return (m_descriptor != NULL)
				&& (SANE_OPTION_IS_ACTIVE (m_descriptor->cap))
				&& (SANE_OPTION_IS_SETTABLE (m_descriptor->cap));
	}
	QWidget* thisWidget ()
	{
		switch (widgetType ())
		{
		case CheckBox:
			return (QWidget*) m_check;
			break;

		case Combo:
			return (QWidget*) m_combo;
			break;

		case Spin:
			return (QWidget*) m_spin;
			break;

		case DoubleSpin:
			return (QWidget*) m_doubleSpin;
			break;

		case LineEdit:
			return (QWidget*) m_lineEdit;
			break;

		default:
			return 0;
			break;
		}
	}

	void setHandle (const SANE_Handle handle)
	{
		m_handle = handle;
		m_descriptor = sane_get_option_descriptor (m_handle, m_index);	// relit le descripteur
		initWidget ();
	}

	void setDisabled () { thisWidget ()->setDisabled (true); }
	void setEnabledIfActive () { thisWidget ()->setEnabled (isActive ()); }

	void stopSignals();
	void startSignals();

signals:
	void guiValueChanged ();
	void mustReloadOptions ();
};


#endif // SANEDEVICEOPTION_H
